/*
 * inotify-sync - a simple file synchronizer and file system watcher
 * Copyright (C) 2010-2011, inotify-sync developers and inotify-sync contributors
 * Copyright (C) 2010-2011, Cohesion Network Security Studio
 *
 * inotify-sync is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * inotify-sync is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with inotify-sync; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

/*
 * FILE:		Syncer.cpp
 * USAGE:		---
 * DESCRIPTION:		---
 * OPTIONS:		---
 * REQUIREMENTS:	---
 * BUGS:		---
 * NOTES:		---
 * AUTHOR:		LI Yiwei (mail:leeyiw@gmail.com)
 * COMPANY:		---
 * VERSION:		1.0
 * CREATED:		Sun Oct  9 17:08:42 CST 2011
 * REVISION:		---
 */

#include "Syncer.h"

Syncer::Syncer(const Profile& profile)
{
	this->profile=profile;
//检测临时文件夹是否存在
//如果存在则先删除文件夹
	int ret=access(profile.get_tmp_path().c_str(),
			R_OK|W_OK|X_OK|F_OK);
	pid_t pid;
	if(ret==0)
	{
		//删除已经存在的临时文件夹
		if((pid=fork())<0)
		{
			perror("fork error");
		}
		else if(pid==0)
		{
			execl("/bin/rm",
				"rm",
				"-rf",
				profile.get_tmp_path().c_str(),
				(char *)0);
		}
		if(waitpid(pid,NULL,0)<0)
		{
			perror("wait error");
		}
	}
//新建文件夹
	mode_t mode=S_IRUSR|S_IWUSR|S_IXUSR|
		S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
	mkdir(profile.get_tmp_path().c_str(),mode);
}

Syncer::~Syncer()
{
	pid_t pid;
	//删除临时文件夹
	if((pid=fork())<0)
	{
		perror("fork error");
	}
	else if(pid==0)
	{
		execl("/bin/rm",
			"rm",
			"-rf",
			profile.get_tmp_path().c_str(),
			(char *)0);
	}
	if(waitpid(pid,NULL,0)<0)
	{
		perror("wait error");
	}
}

void
Syncer::sync_create_file(string abs_path)
{
	if(YES!=profile.get_sync_create_file())
		return;
	string dest_abs_path=get_dest_path(abs_path);
	pid_t pid;
	if((pid=fork())<0)
	{
		perror("fork error");
	}
	else if(pid==0)
	{
	//	int ret=
		execl("/bin/cp",
			"cp",
			abs_path.c_str(),
			dest_abs_path.c_str(),
			(char *)0);
	}
	if(waitpid(pid,NULL,0)<0)
	{
		perror("wait error");
	}
	return;
}

void
Syncer::sync_create_dir(string abs_path)
{
	if(YES!=profile.get_sync_create_dir())
		return;
	string dest_abs_path=get_dest_path(abs_path);
	pid_t pid;
	if((pid=fork())<0)
	{
		perror("fork error");
	}
	else if(pid==0)
	{
	//	int ret=
			execl("/bin/cp",
				"cp",
				"-R",
				abs_path.c_str(),
				dest_abs_path.c_str(),
				(char *)0);
	}
	if(waitpid(pid,NULL,0)<0)
	{
		perror("wait error");
	}
	return;
}

void
Syncer::sync_delete(string abs_path)
{
	if(YES!=profile.get_sync_delete())
		return;
	string dest_abs_path=get_dest_path(abs_path);
	pid_t pid;
	if((pid=fork())<0)
	{
		perror("fork error");
	}
	else if(pid==0)
	{
	//	int ret=
			execl("/bin/rm",
				"rm",
				"-rf",
				dest_abs_path.c_str(),
				(char *)0);
	}
	if(waitpid(pid,NULL,0)<0)
	{
		perror("wait error");
	}
	return;
}

void
Syncer::sync_modify(string abs_path)
{
	if(YES!=profile.get_sync_modify())
		return;
	string dest_abs_path=get_dest_path(abs_path);
	pid_t pid;
	if((pid=fork())<0)
	{
		perror("fork error");
	}
	else if(pid==0)
	{
	//	int ret=
			execl("/bin/cp",
				"cp",
				abs_path.c_str(),
				dest_abs_path.c_str(),
				(char *)0);
	}
	if(waitpid(pid,NULL,0)<0)
	{
		perror("wait error");
	}
	return;
}

void
Syncer::sync_moved_from(string abs_path,uint32_t cookie)
{
	if(YES!=profile.get_sync_moved_from())
		return;
	string dest_abs_path=get_dest_path(abs_path);
	string tmp_file=profile.get_tmp_path()+"/"+Conv.conv<string>(cookie);
	pid_t pid;
	if((pid=fork())<0)
	{
		perror("fork error");
	}
	else if(pid==0)
	{
/*在处理moved_from事件的时候，
 *均先将文件移动到被监控根目录的子目录
 *.isync中，并且以cookie命名，
 *以便在后续确认为内部移动时，
 *直接mv，节省时间，达到系统设计核心思想
 */
		execl("/bin/mv",
			"mv",
			dest_abs_path.c_str(),
			tmp_file.c_str(),
			(char *)0);
	}
	if(waitpid(pid,NULL,0)<0)
	{
		perror("wait error");
	}
	return;
}

void
Syncer::sync_moved_to(string abs_path)
{
	if(YES!=profile.get_sync_moved_to())
		return;
	string dest_abs_path=get_dest_path(abs_path);
	pid_t pid;
	if((pid=fork())<0)
	{
		perror("fork error");
	}
	else if(pid==0)
	{
		execl("/bin/cp",
			"cp",
			"-R",
			abs_path.c_str(),
			dest_abs_path.c_str(),
			(char *)0);
	}
	if(waitpid(pid,NULL,0)<0)
	{
		perror("wait error");
	}
	return;
}

void
Syncer::sync_move_inside(string abs_path,uint32_t cookie)
{
	if(YES!=profile.get_sync_move_inside())
		return;
//生成目标路径，必定会使用到
	string dest_abs_path=get_dest_path(abs_path);
//先判断tmp目录是否存在需要拷贝的cookie文件
	string tmp_file=profile.get_tmp_path()+"/"+Conv.conv<string>(cookie);
	int ret=access(tmp_file.c_str(),R_OK|W_OK|F_OK);
//如果存在
	pid_t pid;
	if((pid=fork())<0)
	{
		perror("fork error");
	}
	else if(pid==0)
	{
		if(ret==0)
		{
			execl("/bin/mv","mv",tmp_file.c_str(),
					dest_abs_path.c_str(),
					(char *)0);
		}
		else
		{
			execl("/bin/cp","cp","-R",abs_path.c_str(),
					dest_abs_path.c_str(),
					(char *)0);
		}
	}
	if(waitpid(pid,NULL,0)<0)
	{
		perror("wait error");
	}
	return;
}

string
Syncer::get_dest_path(string src_abs_path)
{
	return src_abs_path.replace(0,
				profile.get_src_path().length(),
				profile.get_dest_path());
}
